home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / Open Transport / Sample Code / DLPI / ATM PCI DLPI / Sources / ATMDLPI.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-03  |  59.5 KB  |  2,005 lines  |  [TEXT/MPS ]

  1. /***********************************************************
  2.     File:        ATMDLPI.c
  3.  
  4.     Contains:    ATM Open Transport Streams PCI DLPI driver
  5.     
  6.     Written by:    
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.     To Do:
  13.  ***********************************************************/
  14.  
  15. /***********************************************************
  16.   INCLUDES
  17.  ***********************************************************/
  18.  
  19. #include "ATMDLPI.h"
  20. #include "PCIRoutines.h"
  21. #include "HWSpecific.h"
  22. #include "ATMDebug.h"
  23.  
  24. /***********************************************************
  25.   EXTERNS
  26.  ***********************************************************/
  27.  
  28. /***********************************************************
  29.   FUNCTION PROTOTYPES
  30.  ***********************************************************/
  31.  
  32. OSErr InitCFMRoutine(CFragInitBlock *theInitBlock);
  33. void TerminateCFMRoutine(void);
  34.  
  35. OSStatus ValidateHardware(RegEntryID *theID);
  36. install_info* GetOTInstallInfo();
  37. Boolean    InitStreamModule(RegEntryID *theID);
  38. void TerminateStreamModule(void);
  39.  
  40. static int atm_open(queue_t* rdq, dev_t* dev, int flag, int sflag, cred_t* creds);
  41. static int atm_close(queue_t* rdq, int flag, cred_t* creds);
  42. static int atm_rput(queue_t* q, mblk_t* mp);
  43. static int atm_rsrv(queue_t* q);
  44. static int atm_wput(queue_t* q, mblk_t* mp);
  45. static int atm_wsrv(queue_t* q);
  46.  
  47. static void atm_ioctl(queue_t* q, mblk_t* mp);
  48. static void atm_flush(queue_t* q, mblk_t* mp);
  49.  
  50. static int ATMDLPI_info_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  51.  
  52. static int ATMDLPI_phy_addr_req(MinorDeviceTableEntry* minorDev, mblk_t* mp); 
  53. static int all_minors_unbound();
  54. static int ATMDLPI_set_phy_addr_req(MinorDeviceTableEntry* minorDev, mblk_t* mp); 
  55.  
  56. static int ATMDLPI_bind_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  57. static int ATMDLPI_unbind_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  58.  
  59. static int validate_pvc(PVCAddress* pvc);
  60. static int validate_aal(AALType aal);
  61. static int validate_traffic(TrafficDesc* traffic);
  62. static int validate_qos(QOSClass qos);
  63.  
  64. static int ATMDLPI_connect_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  65. static int ATMDLPI_disconnect_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  66.  
  67. static int disconnect_all_pvc(MinorDeviceTableEntry* minorDev);
  68. static int disconnect_pvc(MinorDeviceTableEntry* minorDev, ConnectTableEntry* conn);
  69.  
  70. static int ATMDLPI_IOCTL_subs_connect(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  71. static int ATMDLPI_IOCTL_subs_disconnect(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  72.  
  73. static int ATMDLPI_udqos_req(MinorDeviceTableEntry* minorDev, mblk_t* mp);
  74.  
  75. static void ATMDLPI_uderror_ind(MinorDeviceTableEntry* minorDev, UInt8 *dest, UInt32 destlen,
  76.                                             UInt32 err, UInt32 uerr);
  77.  
  78. static int ATMDLPI_unitdata_req(MinorDeviceTableEntry* minorDev, mblk_t* mp, UInt8 defaultQFlag);
  79. void ATMDLPI_unitdata_ind(ConnectTableEntry* conn, UInt16 vpi, UInt16 vci, mblk_t* mp);
  80.  
  81. static int ATMDLPI_error_ack(MinorDeviceTableEntry* minorDev, mblk_t *ack_mp, UInt32 prim,
  82.                                             UInt32 err, UInt32 uerr);
  83. static int ATMDLPI_ok_ack(MinorDeviceTableEntry* minorDev, mblk_t* mp, UInt32 primitive);
  84.  
  85. static void enable_write_queue(SInt32 p);
  86. static void schedule_write_queue(MinorDeviceTableEntry* minorDev, SInt32 size);
  87.  
  88. ConnectTableEntry* find_connection(UInt16 vpi, UInt16 vci, UInt32 flags);
  89.  
  90. /***********************************************************
  91.   GLOBALS
  92.  ***********************************************************/
  93.  
  94. PortPrivateData*    gPortPrivateData = NULL;                           
  95.  
  96. static char tempstr[255];
  97.  
  98. //-----------------------------------------------------------------------------------------
  99. // STREAMS Structures
  100. //-----------------------------------------------------------------------------------------
  101.  
  102. static struct module_info moduleInformation = 
  103.     {
  104.     kATMModuleID,                    // indicates this dlpi is ethernet 
  105.     kModuleDeviceInfoName,
  106.     kMinAAL5PDU,                    // minimum packet data size
  107.     kMaxAAL5PDU,                    // maximum packet data size 
  108.     kQueueHighMark,                    // Hi water mark for queue
  109.     kQueueLowMark                    // Lo water mark for queue
  110.     };
  111.  
  112.  
  113. static struct qinit    readSide = 
  114.     {
  115.     atm_rput,            /* the read put routine should never be called    */
  116.     atm_rsrv,            /* Service routine for "incoming" data            */
  117.     atm_open,            /* Our open routine                                */
  118.     atm_close,             /* Our close routine                            */
  119.     NULL,                /* reserved for future use                        */
  120.     &moduleInformation,
  121.     NULL                /* no module_stat structure                        */
  122.     };
  123.  
  124.  
  125. static struct qinit    writeSide = 
  126.     {
  127.     atm_wput,            /* Our write-side "put" routine                    */
  128.     atm_wsrv,            /* service routine on the write_side queue        */
  129.     NULL,                /* no module open needed for write side            */
  130.     NULL,                /* no module close needed for write side        */
  131.     NULL,                /* reserved for future use                        */
  132.     &moduleInformation,
  133.     NULL                /* no module_stat structure                        */
  134.     };
  135.  
  136.  
  137. static struct streamtab streamTabInformation = 
  138.     {
  139.     &readSide,
  140.     &writeSide,
  141.     NULL,                /* lower read/write qinit (multiplexors only)    */
  142.     NULL
  143.     };
  144.  
  145. static struct install_info theInstallInformation =
  146.     {
  147.     &streamTabInformation,             
  148.     kOTModIsDriver,                         // install flags 
  149.     SQLVL_MODULE,                            // Synchronization level 
  150.     0,                                        // Shared writer list buddy 
  151.     0                                        // Flag - set to 0 
  152.     };
  153.  
  154. //-----------------------------------------------------------------------------------------
  155. //    Description:
  156. //        This data stucture entry point is exported through the cfm mechanism.  Information
  157. //        about the hardware that this driver works with is located in this structure.
  158. //
  159. //-----------------------------------------------------------------------------------------
  160.  
  161. DriverDescription TheDriverDescription =
  162. {
  163. // Signature Info
  164.     kTheDescriptionSignature,                    // signature always first
  165.     kInitialDriverDescriptor,                    // version second
  166.  
  167. // Type Info
  168.     kPCIDeviceInfoName,                            // Our name, module info name must match
  169.     1,0,0,0,                                    // Major, Minor, Stage, Rev
  170.  
  171. // OS Runtime Info
  172.     kDriverIsUnderExpertControl,                // Runtime Options
  173.     "\patm",                                    // should be kATMName (as a pascal string)
  174.     0,0,0,0,0,0,0,0,                            // reserve 8 longs
  175.  
  176. // OS Service Info
  177.     1,                                            // Number of Service Categories                            
  178.     kServiceCategoryOpenTransport,                // We support the 'otan' category
  179.     OTPCIServiceType(kOTATMDevice,0,0,1),
  180.     1,0,0,0                                        // Major, Minor, Stage, Rev
  181. };
  182.  
  183.  
  184. /*
  185. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  186. +                                                          +
  187. +  F U N C T I O N S                                       +
  188. +                                                          +
  189. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  190. */
  191.  
  192. /***********************************************************
  193. *
  194. *  CODE FRAGMENT MANAGER INITIALIZATION AND TERMINATION
  195. *
  196. ************************************************************/
  197.  
  198. //-----------------------------------------------------------------------------------------
  199. //    Description:
  200. //        This is the cfm initialization routine.  It is not required and is almost a 
  201. //        duplication of the InitStreamModule() routine.
  202. //
  203. //    Input:
  204. //        theInitBlock - block containing various cfm information
  205. //
  206. //    Output:
  207. //        NONE
  208. //
  209. //-----------------------------------------------------------------------------------------
  210. OSErr InitCFMRoutine(CFragInitBlock *theInitBlock)
  211. {
  212.     return kOTNoError;
  213. }
  214.  
  215. //-----------------------------------------------------------------------------------------
  216. //    Description:
  217. //        This is the cfm termination routine.  It is not required and is almost a 
  218. //        duplication of the TerminateStreamModule() routine.
  219. //
  220. //    Input:
  221. //        NONE
  222. //
  223. //    Output:
  224. //        NONE
  225. //
  226. //-----------------------------------------------------------------------------------------
  227. void TerminateCFMRoutine(void)
  228. {
  229.  
  230. }
  231.  
  232. /***********************************************************
  233. *
  234. *  ATM DRIVER DLPI : INSTALLATION AND INITIALIZATION
  235. *
  236. ************************************************************/
  237.  
  238. //-----------------------------------------------------------------------------------------
  239. //    Description:
  240. //        This routine is used by the driver to validate that our hardware is available.
  241. //        By using the ID we can find out the assigned address of the card.
  242. //        Next we should check if this driver can work with that card.  If the driver can 
  243. //        use the card then return kOTNoError.  If your card can be accessed
  244. //        through either address space it is better to use memory space so you don't
  245. //        have to use the Expansion Manager for every access.
  246. //
  247. //        Keep in mind that even if the dlpi responds with kOTNoError the user may decide
  248. //        to not use your card...so the card state should be in the same state as when
  249. //        the routine was called.  In other words, turn off the card before you leave
  250. //        this routine and also deallocate any memory that you allocating.  The dlpi
  251. //        may be unloaded from memory so do not expect to have globals between the
  252. //        the ValidateHardware routine and InitStreamModule.
  253. //    
  254. //    Input:
  255. //        theID - node id of the card in the system registry
  256. //
  257. //    Output:
  258. //        kOTNoError if the hardware is available
  259. //        kENXIOErr, if could not obtain card base address or driver does not work with card
  260. //
  261. //-----------------------------------------------------------------------------------------
  262. OSStatus ValidateHardware(RegEntryID *theID)
  263. {
  264.     OSStatus    error = kENXIOErr;        // default error code
  265.     UInt32        cardAddress, spaceAllocated;
  266.     
  267.     if ( GetPCICardBaseAddress(theID, &cardAddress,
  268.                 kPCIConfigBase14Offset, &spaceAllocated) == kOTNoError)    
  269.         {            // check if our driver works with this card
  270.         if (ABCVendorIsThisOurCard(theID, cardAddress))    
  271.             error = kOTNoError;
  272.         }
  273.         
  274.     return error;
  275. }
  276.  
  277. //-----------------------------------------------------------------------------------------
  278. //    Description:
  279. //        This routine returns a pointer to the install_info structure.  The
  280. //        name of the routine must be "GetOTInstallInfo" because OT loads the
  281. //        the function pointer by name.
  282. //
  283. //    Input:
  284. //        NONE
  285. //
  286. //    Output:
  287. //        returns the install_info pointer
  288. //
  289. //-----------------------------------------------------------------------------------------
  290. install_info* GetOTInstallInfo(void)
  291. {
  292. //    DEBUG_BREAK("atmdlpi: GetOTInstallInfo:");
  293.  
  294.     return &theInstallInformation;
  295. }
  296.  
  297. //-----------------------------------------------------------------------------------------
  298. //    Description:
  299. //        This routine is required and will only be called once.  The routine must
  300. //        call OTInitModule().  At this point Open Transport has made the decision to
  301. //        use our card for a network connection.  We must save the RegEntryID in case
  302. //        we need it later.  We should get the card assigned address and save
  303. //        it in the dlpi private data area.  The hw must be initialized and memory
  304. //        allocated for dma buffers, install isrs, ....
  305. //
  306. //        Open Transport will start calling our open, put, and service routines after
  307. //        this routine if we return true.
  308. //    
  309. //    Input:
  310. //        theID - node id of the card in the system registry
  311. //
  312. //    Output:
  313. //        true, if initialization was successful
  314. //        false, if initialization failed
  315. //
  316. //-----------------------------------------------------------------------------------------
  317. Boolean    InitStreamModule(RegEntryID *theID)
  318. {
  319.     Boolean    initOK;
  320.     int        j;
  321.     
  322. //    initOK = OTInitModule();    ****** These lines need to be present for OT 1.0 ******
  323. //    if (initOK) {                ****** These lines need to be present for OT 1.0 ******
  324.     
  325.         /* allocate memory and initiallize gPortPrivateData */
  326.     
  327.         gPortPrivateData = (PortPrivateData*) PoolAllocateResident(sizeof(PortPrivateData), kTrue);
  328.         if (gPortPrivateData == NULL) {
  329.             goto Terminate;
  330.         }
  331.  
  332.         gPortPrivateData->port            = 0;        // use something similar to OTFindPortByDev(*dev, kATMName)
  333.         gPortPrivateData->numCardOpens    = 0;
  334.         gPortPrivateData->nodeEntryID    = *theID;    // copy out Node Registry ID
  335.             
  336.         gPortPrivateData->minorDeviceTable
  337.             = (MinorDeviceTableEntry**) PoolAllocateResident(sizeof(MinorDeviceTableEntry*) * MAX_MINORDEVICES, kTrue);
  338.         if (gPortPrivateData->minorDeviceTable == NULL) {
  339.             goto Terminate;
  340.         }
  341.         for (j=0; j < MAX_MINORDEVICES; j++)
  342.             gPortPrivateData->minorDeviceTable[j] = 0;
  343.     
  344.         gPortPrivateData->connectTable
  345.             = (ConnectTableEntry**) PoolAllocateResident(sizeof(ConnectTableEntry*) * MAX_CONNECTIONS, kTrue);
  346.         if (gPortPrivateData->connectTable == NULL) {
  347.             goto Terminate;
  348.         }
  349.         for (j=0; j < MAX_CONNECTIONS; j++)
  350.             gPortPrivateData->connectTable[j] = 0;
  351.         gPortPrivateData->maxConnectTableIndex = 0;
  352.  
  353.         initOK = ABCVendorInit(theID);            // gDLPIPrivateData is set in this routine
  354.         
  355.         // was initialization successful?
  356.         if (!initOK) {
  357.             goto Terminate;
  358.         }
  359.  
  360.         /* copy the ATM Physical address into the gPortPrivateData structure */
  361.         ABCVendorGetFactoryATMAddress(gPortPrivateData->ourPhyAddress);
  362.  
  363.         /* copy the Peak Cell Rate into the gPortPrivateData structure */
  364.         gPortPrivateData->ourPeakCellRate = ABCVendorGetPeakCellRate();
  365.  
  366.         /* zero out the current allocated peak rates */
  367.         gPortPrivateData->currentFwdPeakCellRateAllocated = 0;
  368.         gPortPrivateData->currentBwdPeakCellRateAllocated = 0;
  369.     
  370. //    }
  371.         
  372.     return initOK;
  373.     
  374. Terminate:
  375. //    OTTerminateModule();        ****** These lines need to be present for OT 1.0 ******
  376.     initOK = false;
  377.     return initOK;
  378. }
  379.  
  380. //-----------------------------------------------------------------------------------------
  381. //    Description:
  382. //        This routine is required and will only be called when the driver is about to be 
  383. //        unloaded.   At this point the driver is going away so we should close down
  384. //        the hardware.  If we get reopened then the InitStreamModule() will get called 
  385. //        again.  The routine must call OTTerminateModule().  
  386. //    
  387. //    Input:
  388. //        NONE
  389. //
  390. //    Output:
  391. //        NONE
  392. //
  393. //-----------------------------------------------------------------------------------------
  394. void TerminateStreamModule(void)
  395. {
  396.     
  397.     if (gPortPrivateData->cardSpecific) {
  398.         ABCVendorTerminate();
  399.         gPortPrivateData->cardSpecific = NULL;
  400.     }
  401.     
  402.     PoolDeallocate(gPortPrivateData->minorDeviceTable);
  403.     PoolDeallocate(gPortPrivateData->connectTable);
  404.     
  405.     PoolDeallocate(gPortPrivateData);
  406.     
  407. //    OTTerminateModule();        ****** These lines need to be present for OT 1.0 ******
  408. }
  409.  
  410. /***********************************************************
  411. *
  412. *  ATM DRIVER DLPI : OPEN / CLOSE
  413. *
  414. ************************************************************/
  415.  
  416. //-----------------------------------------------------------------------------------------
  417. //    Description:
  418. //        This routine is called each time a new stream is created.  A 
  419. //        MinorDeviceTableEntry is allocated and then filled in accordingly.
  420. //        A pointer to the MinorDeviceTableEntry is stored in the minorDevice
  421. //        table of gPortPrivateData and also in the q_ptr field of the stream queue.
  422. //
  423. //    Input:
  424. //        rdq - read queue
  425. //        dev - device number that consists of major and minor
  426. //        flag - not currently used
  427. //        sflag - indicates special open options
  428. //        creds - not currently used
  429. //
  430. //    Output:
  431. //        kOTNoError, if no problem occurred
  432. //        error, if no memory or the client tried to open as a module instead of cloneopen
  433. //
  434. //-----------------------------------------------------------------------------------------
  435. static int atm_open(queue_t* rdq, dev_t* dev, int flag, int sflag, cred_t* creds)
  436. {
  437.     OSStatus                err;
  438.     size_t                    idx;
  439.     MinorDeviceTableEntry*    theMinorDev;
  440.     UInt8                    addressArray[kATMPhysicalAddressLength];
  441.     
  442. //    DEBUG_BREAK("atmdlpi: atm_open:");
  443.  
  444.     /*
  445.      * Make sure caller is properly credentialed
  446.      */
  447.     if ( (err = drv_priv(creds)) != kOTNoError )
  448.         return err;
  449.     /*
  450.      * If we're being reopened - just return
  451.      */
  452.     if ( rdq->q_ptr != NULL )
  453.         return kOTNoError;
  454.     /*
  455.      * Make sure we're being opened properly - We only allow
  456.      * a "clone" open.
  457.      */
  458.     if ( sflag != CLONEOPEN )
  459.         return EINVAL;
  460.         
  461.     /*
  462.     * Record the number of clients for this card
  463.     */
  464.     gPortPrivateData->numCardOpens++;
  465.     
  466.     /*
  467.      * Find a minor number we can use
  468.      */
  469.     for (idx = 0; idx < MAX_MINORDEVICES; ++idx)
  470.         if ( gPortPrivateData->minorDeviceTable[idx] == 0 )
  471.             break;
  472.     /*
  473.      * If we're out of minor numbers - return an error
  474.      */
  475.      
  476.     if ( idx >= MAX_MINORDEVICES )
  477.         return ENOMEM;
  478.         
  479.     theMinorDev = gPortPrivateData->minorDeviceTable[idx]
  480.                             = (MinorDeviceTableEntry*) PoolAllocateResident(sizeof(MinorDeviceTableEntry), kTrue);
  481.  
  482.     theMinorDev->minorTableIndex    = idx;
  483.     theMinorDev->minorNum            = idx + kFirstMinorNumber;
  484.     theMinorDev->dlstate            = DL_UNBOUND;
  485.     theMinorDev->rdq                = (queue_t *) rdq;
  486.     theMinorDev->numConnections     = 0;
  487.     theMinorDev->useUDInd             = 0;
  488.     theMinorDev->firstConnection    = (ConnectTableEntry *)0;
  489.         
  490.     /*
  491.      * Set our device number so STREAMS knows what we are
  492.      */
  493.     *dev = makedevice(getemajor(*dev), idx + kFirstMinorNumber);
  494.     
  495.     rdq->q_ptr = (void *) theMinorDev;
  496.     WR(rdq)->q_ptr    = rdq->q_ptr;
  497.  
  498.     /*
  499.      * return no error
  500.      */
  501.     return kOTNoError;
  502. }
  503.  
  504. //-----------------------------------------------------------------------------------------
  505. //    Description:
  506. //        This routine closes a stream. All VCs are disconnected and then
  507. //        the memory for the MinorDeviceTableEntry is deallocated.
  508. //
  509. //    Input:
  510. //        rdq - read queue
  511. //        flag - not currently used
  512. //        creds - not currently used
  513. //
  514. //    Output:
  515. //        always return kOTNoError
  516. //
  517. //-----------------------------------------------------------------------------------------
  518. static int atm_close(queue_t* rdq, int flag, cred_t* creds)
  519. {
  520.     MinorDeviceTableEntry*    theMinorDev = (MinorDeviceTableEntry *) rdq->q_ptr;
  521.     OSStatus                 err;
  522.     
  523.     if (theMinorDev == NULL) {
  524.         ERROR_BREAK("atmdlpi: atm_close: null q_ptr\n");
  525.         return ENXIO;
  526.     }
  527.  
  528.     /* remove any timer call */
  529.     if (theMinorDev->idType == kdlpiBufcallType)
  530.         unbufcall(theMinorDev->timeoutID);
  531. //    else if (theMinorDev->idType == kdlpiTimerType)
  532. //        untimeout(theMinorDev->timeoutID);
  533.     
  534.     err = disconnect_all_pvc(theMinorDev);
  535.     rdq->q_ptr        = NULL;
  536.     WR(rdq)->q_ptr    = NULL;
  537.     
  538.     /*
  539.      * Free my minor number and the firstConnection
  540.      * Zero out the q_ptr.  If we allocated any memory and stored
  541.      * it there, now would be a good time to free it!
  542.      */
  543.     gPortPrivateData->minorDeviceTable[theMinorDev->minorTableIndex] = 0;
  544.     PoolDeallocate(theMinorDev);
  545.  
  546.     gPortPrivateData->numCardOpens--;
  547.  
  548.     /*
  549.      * Return no error
  550.      */
  551.     return kOTNoError;
  552. }
  553.  
  554. /***********************************************************
  555. *
  556. *  ATM DRIVER DLPI : WRITE SIDE
  557. *
  558. ************************************************************/
  559.  
  560. //-----------------------------------------------------------------------------------------
  561. //    Description:
  562. //        This routine is called when someone wants to put something on our write queue.
  563. //        Somethings are handled immediately and some are put on the write queue and
  564. //        then serviced during the write service routine.  If a message is received that
  565. //        the driver is not expecting then it is dropped on the floor.
  566. //
  567. //    Input:
  568. //        q - the write queue 
  569. //        mp - message that we need to process
  570. //
  571. //    Output:
  572. //        returns true
  573. //
  574. //-----------------------------------------------------------------------------------------
  575. static int atm_wput(queue_t* q, mblk_t* mp)
  576. {
  577.     union DL_primitives     *dlp;
  578.     UInt32                     prim;
  579.     
  580.     MinorDeviceTableEntry*    theMinorDev = (MinorDeviceTableEntry *) q->q_ptr;
  581.     
  582. //    DEBUG_BREAK("atmdlpi: atm_wput: ");
  583.  
  584. //    DUMP_DLPI_MSG(mp);
  585.     
  586.     if (theMinorDev == NULL) {
  587.         ERROR_BREAK("atmdlpi: atm_wput: null q_ptr\n");
  588.         return ENXIO;
  589.     }
  590.  
  591.     switch (mp->b_datap->db_type) {
  592.         case M_DATA:
  593.         {
  594.             /*
  595.              * Handle M_DATAs really fast !
  596.              */
  597.             if ((qsize(q)) ||
  598.                 (ATMDLPI_unitdata_req(theMinorDev, mp, 1  /* use default PVC */)==kdlpiRETRY) )
  599.                 putq(q, mp);
  600.  
  601.             break;
  602.         }
  603.  
  604.         case M_PROTO:
  605.         case M_PCPROTO:
  606.             dlp = (union DL_primitives *)mp->b_rptr;
  607.             prim = dlp->dl_primitive;
  608.             if (prim == DL_UNITDATA_REQ) {
  609.  
  610.                 /*
  611.                  * Handle DL_UNITDATA_REQs really fast !
  612.                  */
  613.                 if ((qsize(q)) ||
  614.                     (ATMDLPI_unitdata_req(theMinorDev, mp, 0 /* get PVC from message */)==kdlpiRETRY) )
  615.                     putq(q, mp);
  616.             }
  617.             /* All other messages go on to the queue */
  618.             else
  619.                 putq(q, mp);
  620.             break;
  621.  
  622.         case M_IOCTL:
  623.             atm_ioctl(q, mp);
  624.             break;
  625.         
  626.         case M_FLUSH:
  627.             atm_flush(q, mp);
  628.             break;
  629.         
  630.         case M_COPYIN:
  631.         case M_COPYOUT:
  632.         case M_ERROR:
  633.         case M_HANGUP:
  634.         case M_IOCACK:
  635.         case M_IOCNAK:
  636.         case M_PCSIG:
  637.         case M_HPDATA:
  638.         case M_STOP:
  639.         case M_START:
  640.         case M_STOPI:
  641.         case M_STARTI:
  642.         case M_READ:
  643.         case M_SETOPTS:
  644.         case M_SIG:
  645.         case M_BREAK:
  646.         case M_DELAY:
  647.         case M_CTL:
  648.         case M_PASSFP:
  649.         case M_RSE:
  650.             freemsg(mp);
  651.             break;
  652.         
  653.         default:
  654.             ERROR_SPRINTF((tempstr,"atmdlpi: atm_wput: Bad mesg type, %x %d\n", mp->b_datap->db_type,*mp->b_rptr));
  655.             ERROR_BREAK(tempstr);
  656.             freemsg(mp);
  657.             break;
  658.         }
  659.     
  660.     return kOTNoError;
  661. }
  662.  
  663. //-----------------------------------------------------------------------------------------
  664. //    Description:
  665. //        This routine handles everything that was deferred (put on the write queue) during
  666. //        the write put routine.  This routine dequeues DLPI messages from the write queue and
  667. //        processes them. If a message is not supported
  668. //        then an error ack is sent to the client.
  669. //
  670. //    Input:
  671. //        q - the write queue
  672. //
  673. //    Output:
  674. //        returns kOTNoError
  675. //
  676. //-----------------------------------------------------------------------------------------
  677. static int atm_wsrv(queue_t* q)
  678. {
  679.     mblk_t*                    mp;
  680.     UInt32                     err, prim;
  681.     union DL_primitives     *dlp;
  682.  
  683.     MinorDeviceTableEntry*    theMinorDev = (MinorDeviceTableEntry *) q->q_ptr;
  684.     
  685. //    DEBUG_BREAK("atmdlpi: atm_wsrv: ");
  686.     
  687.     if (theMinorDev == NULL) {
  688.         ERROR_BREAK("atmdlpi: null q_ptr\n");
  689.         return ENXIO;
  690.     }
  691.  
  692.     /* there should be only M_PROTO/PCPROTO messages here */
  693.  
  694.     while ( (mp = getq(q)) != NULL ) {
  695.  
  696. //        DUMP_DLPI_MSG(mp);
  697.     
  698.         if (mp->b_datap->db_type==M_DATA) {
  699.             if (ATMDLPI_unitdata_req(theMinorDev, mp, 1  /* use default PVC */)==kdlpiRETRY) {
  700.                 putbq(q, mp);
  701.                 return kOTNoError;
  702.             }
  703.         }
  704.         else if ( mp->b_datap->db_type==M_PROTO || mp->b_datap->db_type==M_PCPROTO) {
  705.         
  706.             /* HANDLE ATM DLPI MESSAGES */
  707.                 
  708.             err = 0;
  709.             dlp = (union DL_primitives *) mp->b_rptr;
  710.             prim = dlp->dl_primitive;
  711.             switch (prim) {
  712.  
  713.                 case DL_UNITDATA_REQ:
  714.                     ERROR_BREAK("atmdlpi: atm_wsrv: DL_UNITDATA_REQ because card transmit is flow controlled\n"); 
  715.                     if (ATMDLPI_unitdata_req(theMinorDev, mp, 0 /* get PVC from message */)==kdlpiRETRY) {
  716.                         putbq(q, mp);
  717.                         return kOTNoError;
  718.                     }
  719.                     break;
  720.                     
  721.                 case DL_INFO_REQ:
  722.                     if (ATMDLPI_info_req(theMinorDev, mp) != kdlpiDONE)
  723.                         ERROR_BREAK("atmdlpi: atm_wsrv: can't respond to DL_INFO_REQ");
  724.                     freemsg(mp);
  725.                     break;
  726.                     
  727.                 case DL_BIND_REQ:
  728.                     if (ATMDLPI_bind_req(theMinorDev, mp) == kdlpiRETRY) {
  729.                         putbq(q, mp);
  730.                         return kOTNoError;
  731.                     }
  732.                     break;
  733.             
  734.                 case DL_UNBIND_REQ:
  735.                     if (ATMDLPI_unbind_req(theMinorDev, mp) == kdlpiRETRY) {
  736.                         putbq(q, mp);
  737.                         return kOTNoError;
  738.                     }
  739.                     break;
  740.             
  741.                 case DL_CONNECT_REQ:
  742.                     if (ATMDLPI_connect_req(theMinorDev, mp) == kdlpiRETRY) {
  743.                         putbq(q, mp);
  744.                         return kOTNoError;
  745.                     }
  746.                     break;
  747.             
  748.                 case DL_DISCONNECT_REQ:
  749.                     if (ATMDLPI_disconnect_req(theMinorDev, mp) == kdlpiRETRY) {
  750.                         putbq(q, mp);
  751.                         return kOTNoError;
  752.                     }
  753.                     break;
  754.             
  755.                 case DL_UDQOS_REQ:
  756.                     if (ATMDLPI_udqos_req(theMinorDev, mp)== kdlpiRETRY) {
  757.                         putbq(q, mp);
  758.                         return kOTNoError;
  759.                     }
  760.                     break;
  761.  
  762.                 case DL_PHYS_ADDR_REQ:
  763.                     if (ATMDLPI_phy_addr_req(theMinorDev, mp)== kdlpiRETRY) {
  764.                         putbq(q, mp);
  765.                         return kOTNoError;
  766.                     }
  767.                     break;
  768.  
  769.                 case DL_SET_PHYS_ADDR_REQ:
  770.                     if (ATMDLPI_set_phy_addr_req(theMinorDev, mp)== kdlpiRETRY) {
  771.                         putbq(q, mp);
  772.                         return kOTNoError;
  773.                     }
  774.                     break;
  775.  
  776.                 case DL_SUBS_BIND_REQ:
  777.                 case DL_SUBS_UNBIND_REQ:
  778.                 case DL_ATTACH_REQ:
  779.                 case DL_DETACH_REQ:
  780.                 case DL_ENABMULTI_REQ:
  781.                 case DL_XID_REQ:
  782.                 case DL_XID_RES:
  783.                 case DL_TEST_REQ:
  784.                 case DL_TEST_RES:
  785.                 case DL_PROMISCON_REQ:
  786.                 case DL_PROMISCOFF_REQ:
  787.                 case DL_CONNECT_RES:
  788.                 case DL_TOKEN_REQ:
  789.                 case DL_RESET_REQ:
  790.                 case DL_RESET_RES:
  791.                 case DL_DATA_ACK_REQ:
  792.                 case DL_REPLY_REQ:
  793.                 case DL_REPLY_UPDATE_REQ:
  794.                     err = DL_NOTSUPPORTED; /* fall through */
  795.                 
  796.                 default:
  797.                     if (err == 0)
  798.                         err = DL_BADPRIM;
  799.                     (void) ATMDLPI_error_ack(theMinorDev, mp, prim, err, 0);
  800.                     break;
  801.             }
  802.         }
  803.         else {
  804.             ERROR_SPRINTF((tempstr,"atmdlpi: atm_wsrv: Bad mesg type, %x %d\n", mp->b_datap->db_type,*mp->b_rptr));
  805.             ERROR_BREAK(tempstr);
  806.             freemsg(mp);
  807.         }
  808.     }
  809.     return kOTNoError;
  810. }
  811.  
  812.  
  813. /***********************************************************
  814. *
  815. *  ATM DRIVER DLPI : READ SIDE
  816. *
  817. ************************************************************/
  818.  
  819. //-----------------------------------------------------------------------------------------
  820. //    Description:
  821. //        This routine is called when someone wants to put something on our read queue.
  822. //        Something is drastically wrong if this ever gets called.
  823. //
  824. //    Input:
  825. //        q - the read queue 
  826. //        mp - message that we need to process
  827. //
  828. //    Output:
  829. //        returns true
  830. //
  831. //-----------------------------------------------------------------------------------------
  832. static int atm_rput(queue_t* q, mblk_t* mp)
  833. {
  834.     ERROR_BREAK("atmdlpi: atm_rput: should never get called");
  835.     return EINVAL;
  836. }
  837.  
  838. //-----------------------------------------------------------------------------------------
  839. //    Description:
  840. //        This routine handles everything that was deferred (put on the read queue) when
  841. //        flow control was experienced in the upward direction.
  842. //
  843. //    Input:
  844. //        q - the read queue
  845. //
  846. //    Output:
  847. //        returns kOTNoError
  848. //
  849. //-----------------------------------------------------------------------------------------
  850. static int atm_rsrv(queue_t* q)
  851. {
  852.     mblk_t*    mp;
  853.     
  854. //    DEBUG_BREAK("atmdlpi: atm_rsrv: ");
  855.  
  856.     /*
  857.      * We know that only M_PROTO (DL_UNITDATA_IND) and M_DATA messages are on the queue,
  858.      * since that is all that we scheduled.
  859.      */
  860.     while ( (mp = getq(q)) != NULL )
  861.     {
  862.  
  863.         DEBUG_BREAK("atmdlpi: atm_rsrv: got a queued message");
  864. //        DUMP_DLPI_MSG(mp);    
  865.  
  866.         /*
  867.          * If we're flow controlled, get out and we'll come back when the flow-
  868.          * control lifts.
  869.          */
  870.         if ( !bcanput(q->q_next, mp->b_band) ) {
  871. //            DEBUG_SPRINTF((tempstr,"atmdlpi: atm_rsrv: q above is full %d\n", q->q_next->q_count));
  872. //            DEBUG_BREAK(tempstr);
  873.             putbq(q, mp);
  874.             return kOTNoError;
  875.         }
  876.         /*
  877.          * Otherwise, send the data upstream, and get some more
  878.          */
  879.         putnext(q, mp);
  880.     }
  881. }
  882.  
  883. /***********************************************************
  884. *
  885. *  ATM DRIVER DLPI : IOCTL HANDLING
  886. *
  887. ************************************************************/
  888.  
  889. //-----------------------------------------------------------------------------------------
  890. //    Description:
  891. //        This routine handles all the ioctl calls made to the driver.  Currently only
  892. //        the DL_IOC_SUBS_CONNECT and the DL_IOC_SUBS_DISCONNECT are handled.  
  893. //
  894. //    Input:
  895. //        q - the write queue
  896. //        mp - the message block that contains ioctl parameters
  897. //
  898. //    Output:
  899. //        NONE
  900. //
  901. //-----------------------------------------------------------------------------------------
  902. static void atm_ioctl(queue_t* q, mblk_t* mp)
  903. {
  904.     struct iocblk*            iocp = (struct iocblk*) mp->b_rptr;
  905.     MinorDeviceTableEntry*    theMinorDev = (MinorDeviceTableEntry *) q->q_ptr;
  906.     OSStatus                err;
  907.  
  908. //    DEBUG_BREAK("atmdlpi: atm_ioctl: ");
  909.  
  910.         
  911.     if (!mp->b_cont) {
  912.         mp->b_datap->db_type = M_IOCNAK;
  913.         iocp->ioc_error = EINVAL;
  914.         iocp->ioc_rval = 0;
  915.     }
  916.     else {
  917.         switch (iocp->ioc_cmd) {
  918.             case DL_IOC_SUBS_CONNECT:
  919.                 err = ATMDLPI_IOCTL_subs_connect(theMinorDev, mp);
  920.                 if (err)
  921.                     ERROR_BREAK("atmdlpi: atm_ioctl: could not complete ATMDLPI_IOCTL_subs_connect");
  922.                 mp->b_datap->db_type = M_IOCACK;
  923.                 iocp->ioc_error = err;
  924.                 iocp->ioc_rval = 0;
  925.                 break;
  926.     
  927.             case DL_IOC_SUBS_DISCONNECT:
  928.                 err = ATMDLPI_IOCTL_subs_disconnect(theMinorDev, mp);
  929.                 if (err)
  930.                     ERROR_BREAK("atmdlpi: atm_ioctl: could not complete ATMDLPI_IOCTL_subs_disconnect");
  931.                 mp->b_datap->db_type = M_IOCACK;
  932.                 iocp->ioc_error = err;
  933.                 iocp->ioc_rval = 0;
  934.                 break;
  935.     
  936.             default:
  937.                 mp->b_datap->db_type = M_IOCNAK;
  938.                 iocp->ioc_count = 0;
  939.                 iocp->ioc_error = EINVAL;
  940.                 iocp->ioc_rval = 0;
  941.         }
  942.     }
  943.  
  944.     qreply(q, mp);
  945.  
  946.     return;
  947. }
  948.  
  949. /***********************************************************
  950. *
  951. *  ATM DRIVER DLPI : FLUSH HANDLING
  952. *
  953. ************************************************************/
  954.  
  955. //-----------------------------------------------------------------------------------------
  956. //    Description:
  957. //        This routine receives the flush call and then it must send it up the read
  958. //        side of the stream.
  959. //
  960. //    Input:
  961. //        q - the write queue
  962. //        mp - the message block that contains the flush parameters
  963. //
  964. //    Output:
  965. //        NONE
  966. //
  967. //-----------------------------------------------------------------------------------------
  968. static void atm_flush(queue_t* q, mblk_t* mp)
  969. {
  970.  
  971.     DEBUG_BREAK("atmdlpi: atm_flush:");
  972.  
  973.     if ( mp->b_rptr[0] & FLUSHW) {
  974.         if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  975.             flushband(q, mp->b_rptr[1], FLUSHALL);
  976.         else
  977.             flushq(q, FLUSHALL);
  978.     }
  979.     if ( mp->b_rptr[0] & FLUSHR ) {
  980.         if ( (mp->b_rptr[0] & FLUSHBAND) && mp->b_wptr - mp->b_rptr == 2 )
  981.             flushband(RD(q), mp->b_rptr[1], FLUSHALL);
  982.         else
  983.             flushq(RD(q), FLUSHALL);
  984.         mp->b_rptr[0] &= ~FLUSHW;
  985.         qreply(q, mp);
  986.         return;
  987.     }
  988.     return;
  989. }
  990.  
  991. /***********************************************************
  992. *
  993. *  ATM DRIVER DLPI : DLPI Message Handling
  994. *
  995. ************************************************************/
  996.  
  997. //-----------------------------------------------------------------------------------------
  998. // reply to DL_INFO_REQ (DL_INFO_ACK generation)
  999. //-----------------------------------------------------------------------------------------
  1000.  
  1001. static int ATMDLPI_info_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1002. {
  1003.     mblk_t*            ack_mp;
  1004.     dl_info_ack_t*    ackp;
  1005.     PVCAddress*        pvc;
  1006.     ATMSimpleQOS*    simpleQOS;
  1007.     ATMVCParams*    connParams;
  1008.     ATMSimpleQOS*    simpleQOSRange;
  1009.  
  1010. //    DEBUG_BREAK("atmdlpi: ATMDLPI_info_req:");
  1011.  
  1012.     if ((ack_mp = allocb(sizeof(dl_info_ack_t) + sizeof(PVCAddress) + 2 * sizeof(ATMSimpleQOS),
  1013.                             BPRI_LO)) == NULL) {
  1014.         ERROR_BREAK("Atm info ack allocb failed");
  1015. //        schedule_write_queue(minorDev, sizeof(dl_info_ack_t));
  1016.         return kdlpiRETRY;
  1017.     }
  1018.  
  1019.     ack_mp->b_datap->db_type = M_PCPROTO;
  1020.     ackp = (dl_info_ack_t *) ack_mp->b_wptr;
  1021.     ackp->dl_primitive        = DL_INFO_ACK;
  1022.     ackp->dl_max_sdu        = kMaxAAL5PDU; 
  1023.     ackp->dl_min_sdu        = kMinAAL5PDU; 
  1024.     ackp->dl_mac_type        = DL_OTHER;
  1025.     ackp->dl_reserved        = 0;
  1026.     ackp->dl_sap_length        = 0;
  1027.     ackp->dl_service_mode    = DL_CODLS;
  1028.     ackp->dl_addr_length    = sizeof(PVCAddress);
  1029.     ackp->dl_addr_offset    = sizeof(dl_info_ack_t);
  1030.     ackp->dl_qos_length        = sizeof(ATMSimpleQOS);
  1031.     ackp->dl_qos_offset        = ackp->dl_addr_offset + ackp->dl_addr_length;
  1032.     ackp->dl_qos_range_length = sizeof(ATMSimpleQOS);
  1033.     ackp->dl_qos_range_offset = ackp->dl_qos_offset + ackp->dl_qos_length;
  1034.     ackp->dl_provider_style = DL_STYLE1;
  1035.     ackp->dl_version        = DL_VERSION_2;
  1036.     ackp->dl_brdcst_addr_length = 0;
  1037.     ackp->dl_brdcst_addr_offset = DL_UNKNOWN;
  1038.     ackp->dl_growth            = 0;
  1039.     ackp->dl_current_state    = minorDev->dlstate;
  1040.  
  1041.     ack_mp->b_wptr += sizeof(dl_info_ack_t);
  1042.     
  1043.     pvc = (PVCAddress*) ack_mp->b_rptr + ackp->dl_addr_offset;
  1044.     *pvc = minorDev->firstConnection->pvc;
  1045.  
  1046.     ack_mp->b_wptr += ackp->dl_addr_length;
  1047.     
  1048.     simpleQOS = (ATMSimpleQOS*) (ack_mp->b_rptr + ackp->dl_qos_offset);
  1049.     simpleQOS->dl_qos_type = DL_QOS_SIMPLE_ATM;
  1050.     connParams = &(simpleQOS->params);
  1051.     connParams->aal        = minorDev->firstConnection->aal;
  1052.     connParams->traffic    = minorDev->firstConnection->traffic;
  1053.     connParams->qos        = minorDev->firstConnection->qos;
  1054.  
  1055.     ack_mp->b_wptr += ackp->dl_qos_length;
  1056.  
  1057.     simpleQOSRange = (ATMSimpleQOS*) (ack_mp->b_rptr + ackp->dl_qos_range_offset);
  1058.     simpleQOSRange->dl_qos_type = DL_QOS_SIMPLE_ATM_RANGE;
  1059.     connParams = &(simpleQOSRange->params);
  1060.     connParams->traffic.fwdPeakCellRate01 = gPortPrivateData->ourPeakCellRate;
  1061.     connParams->traffic.bwdPeakCellRate01 = gPortPrivateData->ourPeakCellRate;
  1062.  
  1063.     ack_mp->b_wptr += ackp->dl_qos_range_length;
  1064.  
  1065.     putnext(minorDev->rdq, ack_mp);
  1066.  
  1067.     return kdlpiDONE;
  1068. }
  1069.  
  1070. //-----------------------------------------------------------------------------------------
  1071. // DL_PHYS_ADDR_REQ handling
  1072. //-----------------------------------------------------------------------------------------
  1073.  
  1074. static int ATMDLPI_phy_addr_req(MinorDeviceTableEntry* minorDev, mblk_t* mp) 
  1075. {
  1076.     mblk_t                 *ack_mp;
  1077.     dl_phys_addr_ack_t    *ackp;
  1078.     dl_phys_addr_req_t     *addrReq = (dl_phys_addr_req_t *) mp->b_rptr;
  1079.     UInt8                addressArray[kATMPhysicalAddressLength];
  1080.  
  1081.     if ((ack_mp = allocb(sizeof(dl_phys_addr_ack_t) + kATMPhysicalAddressLength, BPRI_HI)) == NULL) {
  1082.         schedule_write_queue(minorDev, DL_PHYS_ADDR_ACK_SIZE + kATMPhysicalAddressLength);
  1083.         return kdlpiRETRY;
  1084.     }
  1085.         
  1086.     ack_mp->b_datap->db_type = M_PCPROTO;
  1087.     ackp = (dl_phys_addr_ack_t *)ack_mp->b_wptr;
  1088.     ackp->dl_primitive = DL_PHYS_ADDR_ACK;
  1089.     ackp->dl_addr_length = kATMPhysicalAddressLength;
  1090.     ackp->dl_addr_offset = sizeof(dl_phys_addr_ack_t);
  1091.     ack_mp->b_wptr += sizeof(dl_phys_addr_ack_t) + kATMPhysicalAddressLength;
  1092.     switch(addrReq->dl_addr_type) {
  1093.         case DL_CURR_PHYS_ADDR:
  1094.             OTCopy48BitAddress(gPortPrivateData->ourPhyAddress, 
  1095.                 ack_mp->b_rptr + ackp->dl_addr_offset);
  1096.             break;
  1097.         case DL_FACT_PHYS_ADDR:
  1098.             ABCVendorGetFactoryATMAddress(addressArray);
  1099.             OTCopy48BitAddress(addressArray, ack_mp->b_rptr + ackp->dl_addr_offset);
  1100.             break;
  1101.         default:
  1102.             break;
  1103.     }
  1104.     
  1105.     freemsg(mp);
  1106.  
  1107.     putnext(minorDev->rdq, ack_mp);
  1108.  
  1109.     return kdlpiDONE;
  1110. }
  1111.  
  1112. static int all_minors_unbound()
  1113. {
  1114.     int    idx;
  1115.  
  1116.     for (idx = 0; idx < MAX_MINORDEVICES; ++idx)
  1117.         if ( (gPortPrivateData->minorDeviceTable[idx] != 0) && gPortPrivateData->minorDeviceTable[idx]->dlstate!=DL_UNBOUND)
  1118.             break;
  1119.  
  1120.     if ( idx >= MAX_MINORDEVICES )
  1121.         return 0;
  1122.     else
  1123.         return 1;
  1124. }
  1125.  
  1126. //-----------------------------------------------------------------------------------------
  1127. // DL_SET_PHYS_ADDR_REQ handling
  1128. //-----------------------------------------------------------------------------------------
  1129.  
  1130. static int ATMDLPI_set_phy_addr_req(MinorDeviceTableEntry* minorDev, mblk_t* mp) 
  1131. {
  1132.     dl_set_phys_addr_req_t     *req = (dl_set_phys_addr_req_t *)mp->b_rptr;
  1133.     SInt32                     length = req->dl_addr_length;
  1134.     mblk_t                     *ack_mp;
  1135.     UInt8                    *physicalAddress = ((UInt8 *)req) + req->dl_addr_offset;
  1136.  
  1137.     // all streams must be unbound, if error abort
  1138.     if (!all_minors_unbound()) {
  1139.         ATMDLPI_error_ack(minorDev, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
  1140.         return kdlpiDONE;
  1141.     }
  1142.  
  1143.      // must only contain ATM address
  1144.     if (length != kATMPhysicalAddressLength) {
  1145.         ATMDLPI_error_ack(minorDev, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
  1146.         return kdlpiDONE;
  1147.     }
  1148.         
  1149.     if ((ack_mp = allocb(DL_OK_ACK_SIZE, BPRI_HI)) == NULL) {
  1150.         schedule_write_queue(minorDev, DL_OK_ACK_SIZE);
  1151.         return kdlpiRETRY;
  1152.     }
  1153.  
  1154.     OTCopy48BitAddress(physicalAddress, gPortPrivateData->ourPhyAddress);
  1155.     ABCVendorSetATMAddress(physicalAddress);
  1156.  
  1157.     (void) ATMDLPI_ok_ack(minorDev, mp, DL_SET_PHYS_ADDR_REQ);
  1158.     
  1159.     return kdlpiDONE;
  1160. }
  1161.  
  1162. //-----------------------------------------------------------------------------------------
  1163. // DL_BIND_REQ handling
  1164. //-----------------------------------------------------------------------------------------
  1165.  
  1166. static int ATMDLPI_bind_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1167. {
  1168.     dl_bind_req_t     *req = (dl_bind_req_t *) mp->b_rptr;
  1169.     UInt16             dlsap = (UInt16)req->dl_sap;
  1170.     dl_bind_ack_t    *ackp  = (dl_bind_ack_t *) mp->b_rptr;
  1171.     
  1172. //    DEBUG_BREAK("atmdlpi: ATMDLPI_bind_req:");
  1173.  
  1174.     if (req->dl_service_mode != DL_CODLS) {
  1175.         (void) ATMDLPI_error_ack(minorDev, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0);
  1176.         return kdlpiDONE;
  1177.     }
  1178.     
  1179.     if (minorDev->dlstate != DL_UNBOUND) {
  1180.         (void) ATMDLPI_error_ack(minorDev, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
  1181.         return kdlpiDONE;
  1182.     }
  1183.  
  1184.     mp->b_wptr = mp->b_rptr;
  1185.  
  1186.     mp->b_datap->db_type = M_PCPROTO;
  1187.     ackp->dl_primitive        = DL_BIND_ACK;
  1188.     ackp->dl_sap            = req->dl_sap;
  1189.     ackp->dl_addr_length     = 0;        
  1190.     ackp->dl_addr_offset = DL_BIND_ACK_SIZE;
  1191.     ackp->dl_max_conind = 0;
  1192.     ackp->dl_xidtest_flg = 0;
  1193.     mp->b_wptr += DL_BIND_ACK_SIZE;
  1194.         
  1195.     minorDev->dlstate = DL_IDLE;
  1196.  
  1197.     putnext(minorDev->rdq, mp);
  1198.     return kdlpiDONE;
  1199. }
  1200.  
  1201. //-----------------------------------------------------------------------------------------
  1202. // DL_UNBIND_REQ handling
  1203. //-----------------------------------------------------------------------------------------
  1204.  
  1205. static int ATMDLPI_unbind_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1206. {
  1207.     
  1208. //    DEBUG_BREAK("atmdlpi: ATMDLPI_unbind_req:");
  1209.  
  1210.     if (minorDev->dlstate != DL_IDLE) {
  1211.         (void) ATMDLPI_error_ack(minorDev, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
  1212.         return kdlpiDONE;
  1213.     }
  1214.     
  1215.     minorDev->dlstate = DL_UNBOUND;
  1216.  
  1217.     (void) ATMDLPI_ok_ack(minorDev, mp, DL_UNBIND_REQ);
  1218.     
  1219.     return kdlpiDONE;
  1220. }
  1221.  
  1222. //-----------------------------------------------------------------------------------------
  1223. // ATMVCParams Validation
  1224. //-----------------------------------------------------------------------------------------
  1225.  
  1226. static int validate_pvc(PVCAddress* pvc)
  1227. {
  1228.     if ( (pvc->addressType != kPVCAddressType) ||
  1229.             (pvc->vpi > 255) ||
  1230.             (pvc->vci == 0) ) {
  1231.         ERROR_BREAK("atmdlpi: validate_pvc: invalid");
  1232.         return 0;
  1233.     }
  1234.     else
  1235.         return 1;
  1236.  
  1237. }
  1238.  
  1239. //-----------------------------------------------------------------------------------------
  1240. // AALType validation
  1241. //-----------------------------------------------------------------------------------------
  1242. static int validate_aal(AALType aal)
  1243. {
  1244.     switch (aal) {
  1245.         case kAALType34:
  1246.         case kAALType5:
  1247.             return 1;
  1248.     
  1249.         case kAALTypeNull:
  1250.         case kAALType1:
  1251.         case kAALType2:
  1252.         case kAALTypeUser:
  1253.         default:
  1254.             ERROR_BREAK("atmdlpi: validate_aal: invalid");
  1255.             return 0;
  1256.     }
  1257. }
  1258.  
  1259. //-----------------------------------------------------------------------------------------
  1260. // TrafficDec validation
  1261. //-----------------------------------------------------------------------------------------
  1262. static int validate_traffic(TrafficDesc* traffic)
  1263. {
  1264.     if (traffic->bstEffortReq) return 1;
  1265.  
  1266.     if ( (gPortPrivateData->currentFwdPeakCellRateAllocated + traffic->fwdPeakCellRate01 > gPortPrivateData->ourPeakCellRate) ||
  1267.         (gPortPrivateData->currentBwdPeakCellRateAllocated + traffic->bwdPeakCellRate01 > gPortPrivateData->ourPeakCellRate) )
  1268.     {
  1269.         ERROR_BREAK("atmdlpi: validate_traffic: invalid");
  1270.         return 0;
  1271.     }
  1272.     else
  1273.         return 1;
  1274. }
  1275.  
  1276. //-----------------------------------------------------------------------------------------
  1277. // QOSClass validation
  1278. //-----------------------------------------------------------------------------------------
  1279. static int validate_qos(QOSClass qos)
  1280. {
  1281.     return 1;
  1282. }
  1283.  
  1284. //-----------------------------------------------------------------------------------------
  1285. // DL_CONNECT_REQ handling
  1286. //-----------------------------------------------------------------------------------------
  1287.  
  1288. static int ATMDLPI_connect_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1289. {
  1290.     union DL_primitives*    dp = (union DL_primitives*) mp->b_rptr;
  1291.     ConnectTableEntry*        conn;
  1292.     UInt32                    idx;
  1293.     OSStatus                err;
  1294.     PVCAddress*                pvc;
  1295.     ATMVCParams*            connParams;
  1296.     ATMSimpleQOS*            simpleQOS;
  1297.     UInt32                    flags;
  1298.     UInt32                    peak_Kilocells;
  1299.  
  1300. //    DEBUG_BREAK("atmdlpi: ATMDLPI_connect_req:");
  1301.  
  1302.     if (minorDev->dlstate != DL_IDLE) {
  1303.         (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_OUTSTATE, 0);
  1304.         return kdlpiDONE;
  1305.     }
  1306.  
  1307.     pvc            = (PVCAddress*) (mp->b_rptr + ((dl_connect_req_t*) dp)->dl_dest_addr_offset);
  1308.     simpleQOS    = (ATMSimpleQOS*) (mp->b_rptr + ((dl_connect_req_t*) dp)->dl_qos_offset);
  1309.     if (simpleQOS->dl_qos_type != DL_QOS_SIMPLE_ATM) {
  1310.         ERROR_BREAK("atmdlpi: ATMDLPI_connect_req: dl_qos_type != DL_QOS_SIMPLE_ATM");
  1311.         (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_BADADDR, 0);
  1312.         return kdlpiDONE;
  1313.     }
  1314.     connParams    = &(simpleQOS->params);
  1315.  
  1316.     flags    = connParams->traffic.fwdPeakCellRate01 > 0 ? kVCIOut : 0;
  1317.     flags    |= connParams->traffic.bwdPeakCellRate01 > 0 ? kVCIIn : 0;
  1318.     if ( (!validate_pvc(pvc)) ||
  1319.             (find_connection(pvc->vpi, pvc->vci, flags) != NULL) ||
  1320.             (!validate_aal(connParams->aal)) ||
  1321.             (!validate_traffic(&(connParams->traffic) )) ||
  1322.             (!validate_qos(connParams->qos)) ) {
  1323.         ERROR_SPRINTF((tempstr,"atmdlpi: ATMDLPI_connect_req: vpi,vci %u,%u can not be accepted\n", pvc->vpi, pvc->vci));
  1324.         ERROR_BREAK(tempstr);
  1325.         (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_BADADDR, 0);
  1326.         return kdlpiDONE;
  1327.     }
  1328.  
  1329.     /*
  1330.      * Allocate and store a free connection table entry.
  1331.      */
  1332.     for (idx = 0; idx < MAX_CONNECTIONS; ++idx)
  1333.         if (gPortPrivateData->connectTable[idx]==0) break;
  1334.     if ( idx >= MAX_CONNECTIONS ) {
  1335.         ERROR_BREAK("atmdlpi: ATMDLPI_connect_req: connection table full\n");
  1336.         (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_SYSERR, ENOMEM);
  1337.         return kdlpiDONE;
  1338.     }
  1339.  
  1340.     minorDev->numConnections++;
  1341.  
  1342.     /*
  1343.      * Look up the connection table entry
  1344.      */
  1345.     minorDev->firstConnection = gPortPrivateData->connectTable[idx] = conn
  1346.                     = (ConnectTableEntry*) OTAllocMem(sizeof(ConnectTableEntry));
  1347.     if (idx > gPortPrivateData->maxConnectTableIndex) gPortPrivateData->maxConnectTableIndex = idx;
  1348.  
  1349.     /*
  1350.      * assign values from the connect_req message into
  1351.      * local storage.
  1352.      */
  1353.     conn->connectTableIndex    = idx;
  1354.     conn->rdq                = minorDev->rdq;
  1355.     conn->parentMinorDevice    = minorDev;
  1356.     conn->nextConnection    = (ConnectTableEntry*) 0;
  1357.     conn->prevConnection    = (ConnectTableEntry*) 0;
  1358.     conn->pvc                = *pvc;
  1359.     conn->aal                = connParams->aal;
  1360.     conn->qos                = connParams->qos;
  1361.     conn->traffic            = connParams->traffic;
  1362.     conn->flags                = flags;
  1363.     
  1364.     /* bump up the current peak rates allocated */
  1365.     if (!connParams->traffic.bstEffortReq) {
  1366.         gPortPrivateData->currentFwdPeakCellRateAllocated += connParams->traffic.fwdPeakCellRate01;
  1367.         gPortPrivateData->currentBwdPeakCellRateAllocated += connParams->traffic.bwdPeakCellRate01;
  1368.     }
  1369.     
  1370.     /* Activate an incoming vci, some cards need to activate outgoing vci too */
  1371.     if (conn->flags & kVCIIn) {
  1372.  
  1373.         err = ABCVendorActivateVCI(conn);
  1374.         if (err) {
  1375.             ERROR_SPRINTF((tempstr,"atmdlpi: ATMDLPI_connect_req: ABCVendorActivateVCI returned error %d\n", err));
  1376.             ERROR_BREAK(tempstr);
  1377.             (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_BADADDR, 0);
  1378.             return kdlpiDONE;
  1379.         }
  1380.     }
  1381.     
  1382.     minorDev->dlstate = DL_DATAXFER;
  1383.  
  1384.     dp = (union DL_primitives *) mp->b_rptr;
  1385.     dp->dl_primitive = DL_CONNECT_CON;
  1386.     mp->b_datap->db_type = M_PROTO;
  1387.  
  1388.     putnext(minorDev->rdq, mp);
  1389.  
  1390.     return kdlpiDONE;
  1391. }
  1392.  
  1393. //-----------------------------------------------------------------------------------------
  1394. // DL_DISCONNECT_REQ handling
  1395. //-----------------------------------------------------------------------------------------
  1396.  
  1397. static int ATMDLPI_disconnect_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1398. {
  1399.     OSStatus                err;
  1400.  
  1401.     
  1402. //    DEBUG_BREAK("atmdlpi: ATMDLPI_disconnect_req:");
  1403.  
  1404.     if (minorDev->dlstate != DL_DATAXFER) {
  1405.         (void) ATMDLPI_error_ack(minorDev, mp, DL_DISCONNECT_REQ, DL_OUTSTATE, 0);
  1406.         return kdlpiDONE;
  1407.     }
  1408.     
  1409.     err = disconnect_all_pvc(minorDev);
  1410.     
  1411.     if ((err==0) && (minorDev->numConnections==0)) {
  1412.         minorDev->dlstate = DL_IDLE;
  1413.         (void) ATMDLPI_ok_ack(minorDev, mp, DL_DISCONNECT_REQ);
  1414.     }
  1415.     else
  1416.         (void) ATMDLPI_error_ack(minorDev, mp, DL_DISCONNECT_REQ, DL_SYSERR, -1);
  1417.  
  1418.     
  1419.     return kdlpiDONE;
  1420. }
  1421.  
  1422. //-----------------------------------------------------------------------------------------
  1423. // Disconnect all PVCs and reset all ConnectTableEntry
  1424. //-----------------------------------------------------------------------------------------
  1425.  
  1426. static int disconnect_all_pvc(MinorDeviceTableEntry* minorDev)
  1427. {
  1428.     ConnectTableEntry*        conn;
  1429.     OSStatus                err = 0;
  1430.  
  1431.     
  1432. //    DEBUG_BREAK("atmdlpi: disconnect_all_pvc:");
  1433.  
  1434.     conn = minorDev->firstConnection;
  1435.  
  1436.     if ((minorDev->numConnections>0) && (conn!=NULL)) {
  1437.         ConnectTableEntry*    curr_con = minorDev->firstConnection;
  1438.         ConnectTableEntry*    next_con;
  1439.  
  1440.         while (curr_con != NULL) {
  1441.             next_con = curr_con->nextConnection;
  1442.             err += disconnect_pvc(minorDev, curr_con);
  1443.             curr_con = next_con;
  1444.         }
  1445.     }
  1446.     
  1447.     return err;
  1448. }
  1449.  
  1450. //-----------------------------------------------------------------------------------------
  1451. // Disconnect a PVC and reset a ConnectTableEntry
  1452. //-----------------------------------------------------------------------------------------
  1453.  
  1454. static int disconnect_pvc(MinorDeviceTableEntry* minorDev, ConnectTableEntry* conn)
  1455. {
  1456.     OSStatus            err = kOTNoError;
  1457.  
  1458.     /* Deactivate an incoming vci, some cards need to activate outgoing vci too */
  1459.     if (conn->flags & kVCIIn) { 
  1460.  
  1461.         err = ABCVendorDeactivateVCI(conn);
  1462.         if (err) {
  1463.             ERROR_SPRINTF((tempstr,"atmdlpi: disconnect_pvc: ABCVendorDeactivateVCI returned error %d\n", err));
  1464.             ERROR_BREAK(tempstr);
  1465.             return err;
  1466.         }
  1467.     }
  1468.     
  1469.     /* bump down the peak rates allocated */
  1470.     if (!conn->traffic.bstEffortReq) {
  1471.         gPortPrivateData->currentFwdPeakCellRateAllocated -= conn->traffic.fwdPeakCellRate01;
  1472.         gPortPrivateData->currentBwdPeakCellRateAllocated -= conn->traffic.bwdPeakCellRate01;
  1473.     }
  1474.     
  1475.     /* reset the relevant places in the MinorDeviceTable
  1476.        and the ConnectTable */
  1477.     if (conn->prevConnection)
  1478.         conn->prevConnection->nextConnection = conn->nextConnection;
  1479.     if (conn->nextConnection)
  1480.         conn->nextConnection->prevConnection = conn->prevConnection;
  1481.  
  1482.     gPortPrivateData->connectTable[conn->connectTableIndex] = 0;
  1483.     OTFreeMem((void*) conn);
  1484.     
  1485.     minorDev->numConnections--;
  1486.  
  1487.     if (minorDev->numConnections==0)
  1488.         minorDev->firstConnection = (ConnectTableEntry *) 0;
  1489.     
  1490.     return err;
  1491. }
  1492.  
  1493. //-----------------------------------------------------------------------------------------
  1494. // ATMDLPI_SUBS_CONNECT Ioctl handling
  1495. //-----------------------------------------------------------------------------------------
  1496.  
  1497. static int ATMDLPI_IOCTL_subs_connect(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1498. {
  1499.     ConnectTableEntry*            conn;
  1500.     UInt32                        idx;
  1501.     OSStatus                    err;
  1502.     SInt32*                        done;
  1503.     PVCAddress*                    pvc;
  1504.     ATMVCParams*                connParams;
  1505.     ATMSimpleQOS*                simpleQOS;
  1506.     UInt32                        flags;
  1507.     UInt32                        peak_Kilocells;
  1508.     union DL_primitives*        dp = (union DL_primitives*) mp->b_cont->b_rptr;
  1509.  
  1510. //    DEBUG_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_connect: ");
  1511.  
  1512.     if ((minorDev->dlstate != DL_IDLE) && (minorDev->dlstate != DL_DATAXFER)) {
  1513.         ERROR_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_connect: DLPI not in DL_DATAXFER or DL_IDLE state\n");
  1514.         return -1;
  1515.     }
  1516.  
  1517.     pvc            = (PVCAddress*) (mp->b_cont->b_rptr + ((dl_connect_req_t*) dp)->dl_dest_addr_offset);
  1518.     simpleQOS    = (ATMSimpleQOS*) (mp->b_cont->b_rptr + ((dl_connect_req_t*) dp)->dl_qos_offset);
  1519.     if (simpleQOS->dl_qos_type != DL_QOS_SIMPLE_ATM) {
  1520.         ERROR_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_connect: dl_qos_type != DL_QOS_SIMPLE_ATM");
  1521.         return -1;
  1522.     }
  1523.     connParams    = &(simpleQOS->params);
  1524.     
  1525.     flags    = connParams->traffic.fwdPeakCellRate01 > 0 ? kVCIOut : 0;
  1526.     flags    |= connParams->traffic.bwdPeakCellRate01 > 0 ? kVCIIn : 0;
  1527.     if ( (!validate_pvc(pvc)) ||
  1528.             (find_connection(pvc->vpi, pvc->vci, flags) != NULL) ||
  1529.             (!validate_aal(connParams->aal)) ||
  1530.             (!validate_traffic(&(connParams->traffic) )) ||
  1531.             (!validate_qos(connParams->qos)) ) {
  1532.         ERROR_SPRINTF((tempstr,"atmdlpi: ATMDLPI_IOCTL_subs_connect: vpi,vci %u,%u can not be validated\n", conn->pvc.vpi, conn->pvc.vci));
  1533.         ERROR_BREAK(tempstr);
  1534.         return -1;
  1535.     }
  1536.  
  1537.  
  1538.     /*
  1539.      * Allocate and store a free connection table entry.
  1540.      */
  1541.     for (idx = 0; idx < MAX_CONNECTIONS; ++idx)
  1542.         if (gPortPrivateData->connectTable[idx]==0) break;
  1543.     if ( idx >= MAX_CONNECTIONS ) {
  1544.         ERROR_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_connect: connection table full\n");
  1545.         return ENOMEM;
  1546.     }
  1547.  
  1548.     minorDev->numConnections++;
  1549.     minorDev->useUDInd = 1;
  1550.  
  1551.     gPortPrivateData->connectTable[idx] = conn = (ConnectTableEntry*) OTAllocMem(sizeof(ConnectTableEntry));
  1552.     if (idx > gPortPrivateData->maxConnectTableIndex) gPortPrivateData->maxConnectTableIndex = idx;
  1553.  
  1554.     /*
  1555.      * assign values from the subs_connect message into
  1556.      * local storage.
  1557.      */
  1558.     conn->connectTableIndex    = idx;
  1559.     conn->rdq                = minorDev->rdq;
  1560.     conn->parentMinorDevice    = minorDev;
  1561.     conn->nextConnection    = (ConnectTableEntry*) 0;
  1562.     conn->prevConnection    = (ConnectTableEntry*) 0;
  1563.     conn->pvc                = *pvc;
  1564.     conn->aal                = connParams->aal;
  1565.     conn->qos                = connParams->qos;
  1566.     conn->traffic            = connParams->traffic;
  1567.     conn->flags                = flags;
  1568.  
  1569.     /*
  1570.      * chain up the connection table entry before the first
  1571.      * connection.
  1572.      */
  1573.     conn->nextConnection = minorDev->firstConnection;
  1574.     conn->prevConnection = 0;
  1575.     minorDev->firstConnection->prevConnection = conn;
  1576.     minorDev->firstConnection = conn;
  1577.  
  1578.     /* bump up the current peak rates allocated */
  1579.     if (!connParams->traffic.bstEffortReq) {
  1580.         gPortPrivateData->currentFwdPeakCellRateAllocated += connParams->traffic.fwdPeakCellRate01;
  1581.         gPortPrivateData->currentBwdPeakCellRateAllocated += connParams->traffic.bwdPeakCellRate01;
  1582.     }
  1583.  
  1584.     /* Activate an incoming vci, some cards need to activate outgoing vci too */
  1585.     if (conn->flags & kVCIIn) {
  1586.  
  1587.         err = ABCVendorActivateVCI(conn);
  1588.         if (err) {
  1589.             ERROR_SPRINTF((tempstr,"atmdlpi: ATMDLPI_connect_req: ABCVendorActivateVCI returned error %d\n", err));
  1590.             ERROR_BREAK(tempstr);
  1591.             (void) ATMDLPI_error_ack(minorDev, mp, DL_CONNECT_REQ, DL_BADADDR, 0);
  1592.             return kdlpiDONE;
  1593.         }
  1594.     }
  1595.     
  1596.     if (minorDev->dlstate == DL_IDLE)
  1597.         minorDev->dlstate = DL_DATAXFER;
  1598.  
  1599.     return 0;
  1600. }
  1601.  
  1602. //-----------------------------------------------------------------------------------------
  1603. // ATMDLPI_SUBS_DISCONNECT Ioctl handling
  1604. //-----------------------------------------------------------------------------------------
  1605.  
  1606. static int ATMDLPI_IOCTL_subs_disconnect(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1607. {
  1608.     ConnectTableEntry*        conn;
  1609.     OSStatus                err;
  1610.     PVCAddress*                pvc;
  1611.     ATMVCParams*            connParams;
  1612.     ATMSimpleQOS*            simpleQOS;
  1613.     UInt32                    flags;
  1614.     union DL_primitives*    dp = (union DL_primitives*) mp->b_cont->b_rptr;
  1615.     
  1616. //    DEBUG_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_disconnect:");
  1617.  
  1618.     if (minorDev->dlstate != DL_DATAXFER) {
  1619.         ERROR_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_disconnect: DLPI not in DATAXFER state\n");
  1620.         return -1;
  1621.     }
  1622.  
  1623.     /*
  1624.      * assign values from the subs_connect message into
  1625.      * local storage.
  1626.      */
  1627.     pvc            = (PVCAddress*) (mp->b_cont->b_rptr + ((dl_connect_req_t*) dp)->dl_dest_addr_offset);
  1628.     simpleQOS    = (ATMSimpleQOS*) (mp->b_cont->b_rptr + ((dl_connect_req_t*) dp)->dl_qos_offset);
  1629.     if (simpleQOS->dl_qos_type != DL_QOS_SIMPLE_ATM) {
  1630.         ERROR_BREAK("atmdlpi: ATMDLPI_IOCTL_subs_disconnect: dl_qos_type != DL_QOS_SIMPLE_ATM");
  1631.         return -1;
  1632.     }
  1633.     connParams    = &(simpleQOS->params);
  1634.     
  1635.     flags    = connParams->traffic.fwdPeakCellRate01 > 0 ? kVCIOut : 0;
  1636.     flags    |= connParams->traffic.bwdPeakCellRate01 > 0 ? kVCIIn : 0;
  1637.  
  1638.     conn = find_connection(pvc->vpi, pvc->vci, flags);
  1639.     
  1640.     if (conn==NULL) return -1;
  1641.     else {
  1642.         err = disconnect_pvc(minorDev, conn);
  1643.     }
  1644.     
  1645.     return err;
  1646. }
  1647.  
  1648. //-----------------------------------------------------------------------------------------
  1649. // DL_UDQOS_REQ handling
  1650. //-----------------------------------------------------------------------------------------
  1651.  
  1652. static int ATMDLPI_udqos_req(MinorDeviceTableEntry* minorDev, mblk_t* mp)
  1653. {
  1654.     ERROR_BREAK("atmdlpi: ATMDLPI_udqos_req: unimplemented");
  1655.     
  1656.     return kOTNoError;
  1657. }
  1658.  
  1659. //-----------------------------------------------------------------------------------------
  1660. // DL_UDERROR_IND generation
  1661. //-----------------------------------------------------------------------------------------
  1662.  
  1663. static void ATMDLPI_uderror_ind(MinorDeviceTableEntry* minorDev, UInt8 *dest, UInt32 destlen,
  1664.                                             UInt32 err, UInt32 uerr)
  1665. {
  1666.     dl_uderror_ind_t    *errp;
  1667.     mblk_t                 *bp;
  1668.     SInt32                 bufsize;
  1669.     
  1670. //    DEBUG_BREAK("atmdlpi: ATMDLPI_uderror_ind:");
  1671.     
  1672.     bufsize = DL_UDERROR_IND_SIZE + destlen;
  1673.  
  1674.     if ((bp = allocb(bufsize, BPRI_HI)) == NULL) {
  1675.         ERROR_BREAK("atmdlpi: ATMDLPI_uderror_ind: allocb failed");
  1676.         return;
  1677.     }
  1678.  
  1679.     bp->b_datap->db_type = M_PROTO;
  1680.     errp = (dl_uderror_ind_t *) bp->b_wptr;
  1681.     errp->dl_primitive = DL_UDERROR_IND;
  1682.     errp->dl_errno = err;
  1683.     errp->dl_unix_errno = uerr;
  1684.     errp->dl_dest_addr_length = destlen;
  1685.     errp->dl_dest_addr_offset = DL_UDERROR_IND_SIZE;
  1686.     bp->b_wptr += DL_UDERROR_IND_SIZE;
  1687.     bcopy((UInt8 *)dest, (UInt8 *)bp->b_wptr, destlen);
  1688.     bp->b_wptr += destlen;
  1689.  
  1690.     putnext(minorDev->rdq, bp);
  1691.     
  1692.     return;
  1693. }
  1694.  
  1695. //-----------------------------------------------------------------------------------------
  1696. // DL_UNITDATA_REQ handling
  1697. //-----------------------------------------------------------------------------------------
  1698.  
  1699. static int ATMDLPI_unitdata_req(MinorDeviceTableEntry* minorDev, mblk_t* mp, UInt8 defaultQFlag)
  1700. {
  1701.     
  1702.     PVCAddress*            transmitPVC;
  1703.     OSStatus            err;
  1704.     ConnectTableEntry*    conn;
  1705.  
  1706.     if (minorDev->dlstate != DL_DATAXFER) {
  1707.         ATMDLPI_uderror_ind(minorDev, mp->b_rptr + ((dl_unitdata_req_t *) mp->b_rptr)->dl_dest_addr_offset,
  1708.                 ((dl_unitdata_req_t *) mp->b_rptr)->dl_dest_addr_length, DL_OUTSTATE, 0);
  1709.         freemsg(mp);
  1710.         return kdlpiDONE;
  1711.     }
  1712.  
  1713.     if (defaultQFlag) {
  1714.     
  1715.         conn = minorDev->firstConnection;
  1716.     
  1717.         err = ABCVendorTransmit(conn, conn->pvc.vpi, conn->pvc.vci, mp);
  1718.         if (err==kFlowControl) {
  1719. //            DEBUG_SPRINTF((tempstr, "atmdlpi: ATMDLPI_unitdata_req: ABCVendorTransmit flow control experienced %ld\n",err));
  1720. //            DEBUG_BREAK(tempstr);
  1721.             return kdlpiRETRY;
  1722.         }
  1723.         if (err) {
  1724.             FATAL_SPRINTF((tempstr, "atmdlpi: ATMDLPI_unitdata_req: ABCVendorTransmit error %ld\n",err));
  1725.             FATAL_BREAK(tempstr);
  1726.             return kdlpiDONE;
  1727.         }
  1728.  
  1729.     }
  1730.     else {
  1731.  
  1732.     mblk_t*        proto_mp = mp;
  1733.  
  1734.         if (((dl_unitdata_req_t *) proto_mp->b_rptr)->dl_dest_addr_length != sizeof(PVCAddress)) {
  1735.             ERROR_BREAK("atmdlpi: atm_wput: length of dest, address in Unit Data req incorrect\n");
  1736.             ATMDLPI_uderror_ind(minorDev, mp->b_rptr + ((dl_unitdata_req_t *) mp->b_rptr)->dl_dest_addr_offset,
  1737.                     ((dl_unitdata_req_t *) mp->b_rptr)->dl_dest_addr_length, DL_BADADDR, 0);
  1738.             freemsg(mp);
  1739.             return kdlpiDONE;
  1740.         }
  1741.  
  1742.         mp = mp->b_cont;
  1743.     
  1744.         transmitPVC = (PVCAddress*) (proto_mp->b_rptr + ((dl_unitdata_req_t *) proto_mp->b_rptr)->dl_dest_addr_offset);
  1745.     
  1746.         err = ABCVendorTransmit((ConnectTableEntry*) NULL, transmitPVC->vpi, transmitPVC->vci, mp);
  1747.         if (err==kFlowControl) {
  1748. //            DEBUG_SPRINTF((tempstr, "atmdlpi: ATMDLPI_unitdata_req: ABCVendorTransmit flow control experienced %ld\n",err));
  1749. //            DEBUG_BREAK(tempstr);
  1750.             return kdlpiRETRY;
  1751.         }
  1752.         if (err) {
  1753.             FATAL_SPRINTF((tempstr, "atmdlpi: ATMDLPI_unitdata_req: ABCVendorTransmit error %ld\n",err));
  1754.             FATAL_BREAK(tempstr);
  1755.             return kdlpiDONE;
  1756.         }
  1757.         
  1758.         proto_mp->b_cont = (mblk_t*) NULL;
  1759.         freeb(proto_mp);
  1760.     }
  1761.  
  1762.     return kdlpiDONE;
  1763. }
  1764.  
  1765. //-----------------------------------------------------------------------------------------
  1766. // DL_UNITDATA_IND generation
  1767. //-----------------------------------------------------------------------------------------
  1768.  
  1769. void ATMDLPI_unitdata_ind(ConnectTableEntry* conn, UInt16 vpi, UInt16 vci, mblk_t* mp)
  1770. {
  1771.     mblk_t*                nmp;
  1772.     UInt8*                dlSrcPtr;
  1773.     dl_unitdata_ind_t     *ind;
  1774.  
  1775. //    DEBUG_SPRINTF((tempstr,"atmdlpi: ATMDLPI_unitdata_ind: vci %u,%u", vpi, vci));
  1776. //    DEBUG_BREAK(tempstr);
  1777.     
  1778.     if ((conn==NULL) && ((conn = find_connection(vpi, vci, kVCIIn))==NULL)) {
  1779.         DEBUG_SPRINTF((tempstr,"atmdlpi: ATMDLPI_unitdata_ind: could not find vci %u,%u", vpi, vci));
  1780.         DEBUG_BREAK(tempstr);
  1781.         freemsg(mp);
  1782.         return;
  1783.     }
  1784.  
  1785.     if ( (conn->parentMinorDevice->useUDInd) &&
  1786.         ((nmp = allocb(kGoodUDIndSize, BPRI_HI)) != NULL) ) {
  1787.  
  1788.         nmp->b_cont = mp;
  1789.         mp = nmp;
  1790.  
  1791.         nmp->b_datap->db_type = M_PROTO;
  1792.             
  1793.         ind = (dl_unitdata_ind_t*) nmp->b_rptr;
  1794.         ind->dl_primitive = DL_UNITDATA_IND;
  1795.         ind->dl_dest_addr_length = 0;
  1796.         ind->dl_dest_addr_offset = 0;
  1797.         ind->dl_src_addr_length = sizeof(PVCAddress);
  1798.         ind->dl_src_addr_offset = sizeof(dl_unitdata_ind_t);
  1799.         ind->dl_group_address = 0;                 /* Standard address i.e. not multicast or broadcast */
  1800.         
  1801.         nmp->b_wptr += (sizeof(dl_unitdata_ind_t) + sizeof(PVCAddress));
  1802.         
  1803.         dlSrcPtr= ((UInt8*)(nmp->b_rptr + ind->dl_src_addr_offset));
  1804.         bcopy( (char *) &(conn->pvc), (char *) dlSrcPtr,  sizeof(PVCAddress));
  1805.     }
  1806.     
  1807.     if ( (conn->rdq->q_next == (queue_t *) 0) || (!bcanput(conn->rdq->q_next, mp->b_band)) ) {
  1808. //        DEBUG_SPRINTF((tempstr,"atmdlpi: ATMDLPI_unitdata_ind: atmdlpi readq is full %d\n", conn->rdq->q_count));
  1809. //        DEBUG_BREAK(tempstr);
  1810.  
  1811.         /*
  1812.          *    ATM Forum ABR/UBR schemes must be invoked here.
  1813.          */
  1814.  
  1815. //        if (qsize(conn->rdq) > kMaxPendingRecvMessages) {
  1816.             freemsg(mp);
  1817. //        }
  1818. //        else {
  1819. //            putq(conn->rdq, mp);
  1820. //        }
  1821.  
  1822.         return;
  1823.     }
  1824.  
  1825.     if (qsize(conn->rdq)) {
  1826.         putq(conn->rdq, mp);
  1827.     }
  1828.     else {
  1829.         putnext(conn->rdq, mp);
  1830.     }
  1831.  
  1832.     return;
  1833. }
  1834.  
  1835. //-----------------------------------------------------------------------------------------
  1836. // DL_ERROR_ACK generation
  1837. //-----------------------------------------------------------------------------------------
  1838.  
  1839. static int ATMDLPI_error_ack(MinorDeviceTableEntry* minorDev, mblk_t *ack_mp, UInt32 prim,
  1840.                                             UInt32 err, UInt32 uerr)
  1841. {
  1842.     dl_error_ack_t *errp;
  1843.     
  1844. //    DEBUG_BREAK("atmdlpi: ATMDLPI_error_ack:");
  1845.     
  1846.     if (ack_mp == NULL) {
  1847.         if ((ack_mp = allocb(DL_ERROR_ACK_SIZE, BPRI_HI)) == NULL) {
  1848.             ERROR_BREAK("atmdlpi: ATMDLPI_error_ack: allocb failed");
  1849.             return kdlpiRETRY;
  1850.         }
  1851.     }
  1852.     else {
  1853.         ack_mp->b_rptr = ack_mp->b_wptr = ack_mp->b_datap->db_base;
  1854.         if (ack_mp->b_cont != (mblk_t *) 0) {
  1855.             freemsg(ack_mp->b_cont);
  1856.             ack_mp->b_cont = (mblk_t *) 0;
  1857.         }
  1858.     }
  1859.  
  1860.     ack_mp->b_datap->db_type = M_PCPROTO;
  1861.     ack_mp->b_rptr = ack_mp->b_wptr = ack_mp->b_datap->db_base;
  1862.     errp = (dl_error_ack_t *)ack_mp->b_rptr;
  1863.     errp->dl_primitive = DL_ERROR_ACK;
  1864.     errp->dl_error_primitive = prim;
  1865.     errp->dl_errno = err;
  1866.     errp->dl_unix_errno = uerr;
  1867.     ack_mp->b_wptr += DL_ERROR_ACK_SIZE;
  1868.  
  1869.     putnext(minorDev->rdq, ack_mp);
  1870.     return kdlpiDONE;
  1871. }
  1872.  
  1873. //-----------------------------------------------------------------------------------------
  1874. // DL_OK_ACK generation
  1875. //-----------------------------------------------------------------------------------------
  1876.  
  1877. static int ATMDLPI_ok_ack(MinorDeviceTableEntry* minorDev, mblk_t* ack_mp, UInt32 primitive)
  1878. {
  1879.     dl_ok_ack_t *ackp;
  1880.     
  1881. //    DEBUG_BREAK("atmdlpi: ATMDLPI_ok_ack:");
  1882.  
  1883.     if (ack_mp == NULL) {
  1884.         if ((ack_mp = allocb(DL_OK_ACK_SIZE, BPRI_HI)) == NULL) {
  1885.             ERROR_BREAK("atmdlpi: ATMDLPI_ok_ack: allocb failed");
  1886.             return kdlpiRETRY;
  1887.         }
  1888.     }
  1889.     else {
  1890.         ack_mp->b_rptr = ack_mp->b_wptr = ack_mp->b_datap->db_base;
  1891.         if (ack_mp->b_cont != (mblk_t *) 0) {
  1892.             freemsg(ack_mp->b_cont);
  1893.             ack_mp->b_cont = (mblk_t *) 0;
  1894.         }
  1895.     }
  1896.         
  1897.     ack_mp->b_datap->db_type = M_PCPROTO;
  1898.     ackp = (dl_ok_ack_t *) ack_mp->b_rptr;
  1899.     ackp->dl_primitive = DL_OK_ACK;
  1900.     ackp->dl_correct_primitive = primitive;
  1901.     ack_mp->b_wptr += DL_OK_ACK_SIZE;
  1902.  
  1903.     putnext(minorDev->rdq, ack_mp);
  1904.     return kdlpiDONE;
  1905. }
  1906.  
  1907.  
  1908. /***********************************************************
  1909. *
  1910. *  ATM DRIVER DLPI : handling out of memory conditions
  1911. *
  1912. ************************************************************/
  1913.  
  1914. #define SECOND                1000000        // in microseconds 
  1915.  
  1916. //-----------------------------------------------------------------------------------------
  1917. //    Description:
  1918. //        This routine is used to enable the write queue.
  1919. //
  1920. //    Input:
  1921. //        p - the stream that contains the write queue that needs to be enabled
  1922. //
  1923. //    Output:
  1924. //        NONE
  1925. //
  1926. //-----------------------------------------------------------------------------------------
  1927. static void enable_write_queue(SInt32 p)
  1928. {
  1929.     MinorDeviceTableEntry*    minorDev = (MinorDeviceTableEntry*) p;
  1930.     
  1931.     if (minorDev->rdq != NULL) {
  1932.         minorDev->idType = NULL;    // mark us as no event waiting 
  1933.         qenable(WR(minorDev->rdq));
  1934.     }
  1935. }
  1936.  
  1937. //-----------------------------------------------------------------------------------------
  1938. //    Description:
  1939. //        This routine is called when someone cannot allocate a message block for an ack
  1940. //        message.  This routine says call me when you have enough memory for my
  1941. //        message block.
  1942. //
  1943. //    Input:
  1944. //        minorDev - the MinorDeviceTableEntry to disable until memory is available
  1945. //        size - number of bytes needed for the message block
  1946. //
  1947. //    Output:
  1948. //        NONE
  1949. //
  1950. //-----------------------------------------------------------------------------------------
  1951. static void schedule_write_queue(MinorDeviceTableEntry* minorDev, SInt32 size)
  1952. {
  1953.     minorDev->timeoutID = bufcall(size, BPRI_HI, enable_write_queue, (SInt32) minorDev);
  1954.     if (minorDev->timeoutID == 0) {    
  1955.         ERROR_BREAK("atmdlpi: schedule_write_queue: bufcall failed");
  1956. //        minorDev->timeoutID = timeout(enable_write_queue, (UInt8 *)minorDev, SECOND);
  1957. //        minorDev->idType = kdlpiTimerType; // oh well, use timeout
  1958.     } 
  1959.     else 
  1960.         minorDev->idType = kdlpiBufcallType;
  1961.  
  1962. }
  1963.  
  1964.  
  1965. /***********************************************************
  1966. *
  1967. *  ATM DRIVER DLPI : Searching the connectTable
  1968. *
  1969. ************************************************************/
  1970.  
  1971. /* The last ConnectTableEntry index successfully returned */ 
  1972. static last_i = 0;
  1973.  
  1974. //-----------------------------------------------------------------------------------------
  1975. // Find the ConnectTableEntry, given the vpi, vci and flags
  1976. // This  could be more efficient :-).
  1977. //-----------------------------------------------------------------------------------------
  1978.  
  1979. ConnectTableEntry* find_connection(UInt16 vpi, UInt16 vci, UInt32 flags)
  1980. {
  1981.     register int i;
  1982.     register ConnectTableEntry*    conn = gPortPrivateData->connectTable[last_i];
  1983.     
  1984.     if ( (conn) &&
  1985.             (vci == conn->pvc.vci) &&
  1986.             (vpi == conn->pvc.vpi) &&
  1987.             ((flags & conn->flags) == flags) )
  1988.         return conn;
  1989.  
  1990.     for (i=0; i<=gPortPrivateData->maxConnectTableIndex; i++) {
  1991.         conn = gPortPrivateData->connectTable[i];
  1992.         if ( (conn) &&
  1993.                 (vci == conn->pvc.vci) &&
  1994.                 (vpi == conn->pvc.vpi) &&
  1995.                 ((flags & conn->flags) == flags) ) {
  1996.             last_i = i;
  1997.             return conn;
  1998.         }    
  1999.     }
  2000.     
  2001. //    DEBUG_BREAK("atmdlpi: find_connection: could not find it");
  2002.  
  2003.     return((ConnectTableEntry *) NULL);
  2004. }
  2005.